Android 垃圾清理原理解析

一、如何定义『程序垃圾』

基本概括由程序运行时生成,占用存储空间,删除后对程序无影响的具有静态特征的文件,包括应用的文件缓存、缩略图、日志等。 对比市面上主流的清理程序,对Android手机中可以清理的垃圾总结如下:

  1. 应用缓存文件
  2. 应用卸载残留
  3. 无用的安装包
  4. 内存数据
  5. 系统垃圾(日志、缩略图、空文件夹等)
  6. 广告文件
  7. 大文件(文件大小大于某个值的文件)
  8. SD卡上的无用文件

二、存储方式及策略

Android 系统对于数据存储方式有两种,外置存储、内置存储。对于这两种存储方式,系统管理 的策略也不相同,对于外置存储,原则上是采取全局共享的策略。而内置存储相反,采用进程隔离的策略。 而内置存储中私有数据一般在 /data/data/packagename/目录下,在非Root的情况下无法对其进行访问,而外置存储一般不需要特殊权限即可访问。

三、什么是『快速清理』和『深度清理』

快速清理:一般指在垃圾扫描时只扫描两到三层目录,暂时不做一些需要深度遍历等的耗时操作。 深度清理:指对所有可清理的垃圾进行全面扫描,对目录进行深度遍历。

二者的看似泾渭分明,实则是可以相互融合的,一个可行测策略是: 在管理软件启动后,选择系统空闲时间,定时做深度扫描,在用户手动触发时做快速扫描。不过这里又引出另外一个问题是:在空闲时扫描要有合适的策略,什么时候开始,什么时候暂停,必须保证在不影响应用正常使用的前提下进行。

四、垃圾清理方案

缓存清理

  1. 计算缓存大小

getPackageSizeInfo 方法是一个 @hide 方法,需要通过反射来调用。 从 PackageManager.java 文件的 getPackageSizeInfo 方法定义处可知,它需要 GET_PACKAGE_SIZE 权限,幸运的是,从 frameworks/base/core/res/AndroidManifex.xml 文件里可知,该权限的 Protection level 为 normal,是可以正常声明的。

1
2
3
4
5
6
<!-- Allows an application to find out the space used by any package. -->
<permission android:name="android.permission.GET_PACKAGE_SIZE"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="normal"
android:label="@string/permlab_getPackageSize"
android:description="@string/permdesc_getPackageSize" />

传给 getPackageSizeInfo 方法的第二个参数类型 IPackageStatsObserver 是在 android.content.pm 包下,需要自已通过 aidl 方式定义。

  1. 利用系统接口实现应用缓存清理

  2. 自己实现应用缓存清理

应用卸载残留清理

方案一:维护文件映射信息

在文件或者数据库中应用包名(唯一)与SD卡上文件的一个映射信息,可以采用应用包名为Key,因为不同应用的包名是唯一的,不会重复;采用SD卡上的文件作为Value,建立映射如下所示:

在检测到应用卸载事件后判断该应用是否有对应的文件存在,有则提示用户删除。采用这种方案时需要如下几个问题:

  1. 映射表的建立:需要对使用频率和用户量较高的应用建立映射表。这里最好有后台提前扫描应用建立,然后下发给客户端;也可以客户端先上报信息到后台,后台修正。映射表的建立是识别的关键。

  2. 错误识别问题:一般来说不同应用的数据放在不同的文件夹中,不会有重复。但在实际中难免会出现重复的情况。对于这种情景有两种处理方式:

  • 映射关系细化到文件,删除完文件后再判断上层文件夹是否为空,为空则删除。
  • 有多个应用的映射关系重复时判断所有应用都已卸载再删除文件夹。

方案二:记录应用安装过程

该方案的普遍性并不如第一种方案强,但也可作为一种实现方案作为参考。方案如下:

  1. 在通过管理软件进行安装时,通过log记录安装应用所产生的文件。在应用运行时,监控SD文件的变化,发现变化时,当前应用(运行时栈顶)即文件的创建者,同样在log中记录这种对应关系。
  2. 在通过管理软件卸载应用时,根据log信息执行逆过程。

安装包清理

无用安装包的清理比较简单。判断无用安装包的标准是:

  1. 存储目录中存在APK文件,但是该APK已被安装
  2. APK文件已损坏 扫描安装包有两种处理方式:
  3. 深度扫描:扫描SD卡上的所有目录
  4. 快速扫描,只扫描手机管理软件(豌豆荚、360手机助手、应用宝等)和浏览器(UCWeb、QQ浏览器)和Download目录。要清理其他下载文件也可以按照这个思路来实现。

系统日志清理

日志文件分为系统日志和应用日志两部分,其各自的存放位置分别为:

  • 系统日志的存放位置如下(不同手机可能会有所差异):
  • /data/local/tmp/*
  • /data/tmp/*
  • /data/system/usagestats/*
  • /data/system/appusagestates/*
  • /data/system/dropbox/*
  • /data/tombstones/*
  • /data/anr/*
  • /dev/log/main
  • 应用日志存放位置可以判断的有:SD卡上后缀名为.log或者log.txt等结尾的文件

清理图片缩略图

在SD卡上的DICM目录下有一个隐藏的目录,名字叫”.thumbnails”,这个目录存放的是系统图片的缓存。清理缓存主要就是清理这个目录。应用目录也可能有缩略图文件,但不容易识别,所以不建议清理,可以放在清理残留数据时一起清理。

清理失效文件与空白文件

判断标准: A. 文件的长度为0则认为是空白文件,可以删除 B. 文件夹中不包含任何文件或文件夹,则认为是空白文件夹,可以删除。 C. 除了上面两种情况外,还可以扫描文件的创建时间,很长时间未使用的文件认为是无效文件。

大文件清理

对于大文件的识别比较简单,只判断文件大小是否超过一定的阀值(例如:豌豆荚认为大小超过10M即为大文件)即可。但这里有两个需要注意的点: A. 大文件一般是视频文件或者应用数据(例如百度map的数据),对于这些文件在清理是建议默为”不选中”状态。 B. 可以充分利用2.2.1中建立的映射关系,对大文件是否建议删除提供更加准确的建议。 对于广告文件等的识别和处理这里不再赘述了,原理都与上面的类似。